\section{option}\label{sec:std_option}
Option 表示值，如果有值则Some包装其值，否则返回None。
\begin{rust}
fn divide(a: f32, b: f32) -> Option<f32> {
    if b == 0.0f32 {
        None
    } else {
        Some(a / b)
    }
}
fn main() {
    let a = 1.0f32;
    let b = 2.0f32;
    let c = 0.0f32;
    let r = divide(a, b);
    println!("r = {:?}", r);
    println!("divide zero = {:?}", divide(a, c));
}

\end{rust}
rust指针必须指向可用的位置，不是为null引用。比较之下，Rust有一个Option指针，类似于Option<Box<T>>。在下面的例子，使用i32的Box创建一个Option。通过模式匹配实现对不同情况的处理：
\begin{rust}
fn check_optional(optional: Option<Box<i32>>) {
    match optional {
        Some(p) => {
            println!("解引用里面的值:{p}");
        }
        None => {
            println! {"Optional为空"};
        }
    }
}
fn main() {
    let optional1 = None;
    check_optional(optional1);
    let optional2 = Some(Box::new(99));
    check_optional(optional2);
}
\end{rust}
Option的简化操作，如果我们要对向量中最后两个元素求和：
\begin{rust}
fn add_last_numbers(s: &mut Vec<i32>) -> Option<i32> {
    let a = s.pop();
    let b = s.pop();
    match (a, b) {
        (Some(x), Some(y)) => Some(x + y),
        _ => None,
    }
}
fn main() {
    let mut a = vec![1, 2, 3, 4];
    let b = add_last_numbers(&mut a);
    println!("b = {:?}", b);
}
\end{rust}
我们也可以：
\begin{rust}
fn add_last_numbers(s: &mut Vec<i32>) -> Option<i32> {
    Some(s.pop()? + s.pop()?)
}
\end{rust}
这里的`?`表达式将对`Some`解包，如果是None则结果还是None。这样就不用对Option的值层层匹配避免冗余操作。

\subsection{Option常用方法}
\begin{itemize}
\item as\_ref:将\&Option<T>转换为Option<\&T>。
\item as\_mut:转换\&mut Option<T>为Option<\&mut T>。
\item as\_deref：转换\&Option<T>为Option<\&T::Target>。
\item as\_deref\_mut：转换\&mut Option<T> 为 Option<\&mut T::Target>。
\item as\_pin\_ref：转换Pin<\&Option<T>为Option<Pin<\&T>。
\item as\_pin\_ref：转换Pin<\&Option<T>>为Option<Pin<\&T>>。
\item as\_pin\_mut：转换Pin<\&mut Option<T>>为Option<Pin<\&mut T>>。
\item expect：如果为None则爆出给定的错误信息。
\item unwrap：如果为None则爆出错误信息否则解包Option里面的元素。
\item unwrap\_or：如果为None则返回给定的值，否则解包。
\item unwrap\_or\_default：返回类型T的默认值。
\item unwrap\_or\_else：返回提供的值。是
\item ok\_or：转换Some(b)为Ok(b)，None为Err(err)。
\item ok\_or\_else：转换Some(v)为Ok(v)、None为Err的值。
\item transpose：转换Option的结果为Result。
\item filter：对Some(t)的t调用函数，如果为Option包含值则函数返回True，否则返回None。
\item map:使用提供的函数转换Option<T>为Option<U>，如果Option为Some则映射转换否则返回None。
\item map\_or：如果Option是Some则返回Some的值，否则返回默认值。
\item map\_or\_else：如果是Some则使用函数，否则返回callback函数的调用结果。
\item zip：如果self是Some(s)提供了Option(o)返回Some((s,o))，否则返回None。
\item zip\_with:调用提供的函数，如果Option是Some(o)提供的Some(s)则返回Some(f(s,o))，否则返回None。
\end{itemize}
\begin{table}
    \caption{Option逻辑运算}
    \label{tab:}
    \begin{center}
        \begin{tabular}{cccc}
            \toprule
            方法&self（Option本身）& 运算输出 \\
            \midrule
 and  & None               & ignore（表示无论是什么输出都一样） & None     \\
 and  & Some(x)            & None                               & None     \\
 and  & Some(x)            & Some(y)                            & Some(y)  \\
 or   & None               & None                               & None     \\
 or   & None               & Some(y)                            & Some(y)  \\
 or   & Some(x)            & ignore                             & Some(x)  \\
 xor  & None               & None                               & None     \\
 xor  & None               & Some(y)                            & Some(y)  \\
 xor  & Some(x)            & None                               & Some(x)  \\
 xor  & Some(x)            & Some(y)                            & None     \\
            \bottomrule
        \end{tabular}
    \end{center}
\end{table}
and\_then和or\_else方法接受函数输入，当有值的时候产生一个新的值，and\_then方法生成一个Option<U>不同于原来的Option<T>类型。
\begin{table}[!htbp]
    \caption{and\_then和or\_else计算规则}
    \label{tab:option_method}
    \begin{center}
        \begin{tabular}{ccccc}
        \toprule
 方法     & self    & function输入 & function result & 输出    \\
        \midrule
 and\_then & None    & 无输入       & 无计算          & None    \\
 and\_then & Some(x) & x            & None            & None    \\
 and\_then & Some(x) & x            & Some(y)         & Some(y) \\
 or\_else  & None    & 无输入       & None            & None    \\
 or\_else  & None    & 无输入       & Some(y)         & Some(y) \\
 or\_else  & Some(x) & 无输入       & 无计算          & Some(x) \\
        \bottomrule
        \end{tabular}
    \end{center}
\end{table}
and\_then或者是or\_else常用在pipeline调用的场景，pipeline中的一个状态计算失败则传递None，否则继续处理Some里面的值。

比较运算符：
如果T本身实现了PartialOrd然后Option<T>将继承它的PartialOrd。结合这个顺序，None<Some，两个Some使用同昂的方法比较的时候比较的是其中的值。如果T也实现了Ord，然后可以Option<T>也是相同的道理。
\begin{rust}
assert!(None < Some(0));
assert!(Some(0) < Some(1));
\end{rust}
在Option上迭代：
\begin{itemize}
\item into\_iter：消耗Option，生成其中包含的值。
\item iter:生成一个无法修改的\&T的值。
\item iter\_mut:生成一个可变值的引用。
\end{itemize}
\begin{rust}
fn main() {
    let yep = Some(4);
    let nope = None;
    //chain方法调用into_iter生成迭代器，这里yep为Some(4)则将4取出
    let nums: Vec<i32> = (0..4).chain(yep).chain(4..8).collect();
    assert_eq!(nums, [0, 1, 2, 3, 4, 4, 5, 6, 7]);
    //chain方法调用into_iter生成迭代器，这里Nope为None则无法取出。
    let nums1: Vec<i32> = (0..4).chain(nope).chain(4..8).collect();
    assert_eq!(nums1, [0, 1, 2, 3, 4, 5, 6, 7]);
}
\end{rust}
Option 实现了FromIterator trait：可以在Option的值上收集值进一个Option集合，如果Option本身有任何一个元素为None则结果为None。
\begin{rust}
fn main() {
    let v = [Some(2), Some(4), None, Some(8)];
    let res: Option<Vec<_>> = v.into_iter().collect();//包含一个None
    assert_eq!(res, None);
    let v = [Some(2), Some(4), Some(8)];
    let res: Option<Vec<_>> = v.into_iter().collect();
    assert_eq!(res, Some(vec![2, 4, 8]));
}
\end{rust}
Option也实现了Product和Sumt rait，允许Option里面的元素累积和累和。
\begin{rust}
fn main(){
   let v = [None, Some(1), Some(2), Some(3)];
let res: Option<i32> = v.into_iter().sum();//包含有None，求和为None
assert_eq!(res, None);
let v = [Some(1), Some(2), Some(21)];
let res: Option<i32> = v.into_iter().product();
assert_eq!(res, Some(42));
}
\end{rust}
原位修改Option：
\begin{itemize}
\item insert：插入一个值，删除老值。
\item get\_or\_insert：获取当前值，如果为None则插入提供的值。
\item get\_or\_insert\_default：获取当前值，插入T类型的默认值（必须实现Default）。
\item get\_or\_insert\_with：获取当前值插入，如果为None则默认函数计算值。
\end{itemize}
转换Option值的所有权：
\begin{itemize}
    \item take：获取Option的值得所有权，如果Option为None的使用None替代。
    \item replace：获取Option值的所有权，如果有任何元素，使用Some(value)替代。
\end{itemize}
\begin{rust}
let msg = Some("howdy");

// Take a reference to the contained string
if let Some(m) = &msg {
    println!("{}", *m);
}

// Remove the contained string, destroying the Option
let unwrapped_msg = msg.unwrap_or("default message");
\end{rust}
循环之前初始化结果为None：
\begin{rust}
enum Kingdom { Plant(u32, &'static str), Animal(u32, &'static str) }

// A list of data to search through.
let all_the_big_things = [
    Kingdom::Plant(250, "redwood"),
    Kingdom::Plant(230, "noble fir"),
    Kingdom::Plant(229, "sugar pine"),
    Kingdom::Animal(25, "blue whale"),
    Kingdom::Animal(19, "fin whale"),
    Kingdom::Animal(15, "north pacific right whale"),
];

// We're going to search for the name of the biggest animal,
// but to start with we've just got `None`.
let mut name_of_biggest_animal = None;
let mut size_of_biggest_animal = 0;
for big_thing in &all_the_big_things {
    match *big_thing {
        Kingdom::Animal(size, name) if size > size_of_biggest_animal => {
            // Now we've found the name of some big animal
            size_of_biggest_animal = size;
            name_of_biggest_animal = Some(name);
        }
        Kingdom::Animal(..) | Kingdom::Plant(..) => ()
    }
}

match name_of_biggest_animal {
    Some(name) => println!("the biggest animal is {name}"),
    None => println!("there are no animals :("),
}
\end{rust}
is\_some:判断Option是否为Some。
